package com.yangcangclub.commons.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * class类相关操作类及一些IO操作
 *
 * @author Humn Chou
 * @version 2013-9-5
 *
 */
public final class ClassUtils {
    /**
     * 取得当前的类加载器
     * @return
     */
    public static ClassLoader getClassLoader() {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader == null) {
            classLoader = ClassUtils.class.getClassLoader();
        }
        return classLoader;
    }

    /**
     * 取得类路径下的输入流
     * @param classPath
     * @return
     */
    public static InputStream getClassPathRes(String classPath) {
        InputStream in = null;
        ClassLoader classLoader = getClassLoader();
        in = classLoader.getResourceAsStream(classPath);
        return in;
    }

    /**
     * 取得某目录下的文件[packageName]里所有文件名
     * @param classesRootDir
     * @param packageName
     * @return
     */
    public static List<String> findResources(File classesRootDir,String packageName) {
        String pkgPath = packageName.replace('.', '/');
        List<String> resourcesList = new ArrayList<String>();
        File packageDir = new File(classesRootDir, pkgPath);
        File[] resources = packageDir.listFiles();
        for (File f : resources) {
            if (!f.isDirectory()) {
                resourcesList.add(pkgPath + "/" + f.getName());
            }
        }
        return resourcesList;
    }

    /**
     * 从文件路径中加载class文件后返回
     * @param classesRootDir
     * @param packageName
     * @return
     */
    public static List<Class<?>> loadClasses(File classesRootDir,String packageName) {
        ClassLoader classLoader = getClassLoader();

        List<Class<?>> klassList = new ArrayList<Class<?>>();
        try {
            List<String> paths = findResources(classesRootDir, packageName);
            for (String klassPath : paths) {
                //取得class文件后加载
                if (klassPath.endsWith(".class")) {
                    String classCanonicalName = klassPath.substring(0,klassPath.lastIndexOf("."));
                    classCanonicalName = classCanonicalName.replace('/', '.');
                    //反射加载
                    Class<?> klass = classLoader.loadClass(classCanonicalName);
                    klassList.add(klass);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Load Classes Error!");
        }
        return klassList;
    }

    /**
     *
     * 取得JAR文件中的文件信息(但中文文件名问题没解决)
     */
    public static List<String> findResourcesInJar(File jarFile,String packageName) {
        try {
            ZipInputStream in = new ZipInputStream(new FileInputStream(jarFile));
            ZipEntry ze = null;
            List<String> jarClasses = new ArrayList<String>();
            String packagePath = packageName.replace(".", "/");

            while ((ze = in.getNextEntry()) != null) {
                if (ze.getName().startsWith(packagePath)
                        && ze.getName().lastIndexOf("/") == packagePath
                        .length()) {
                    if (ze.getName().lastIndexOf(".") != -1) {
                        jarClasses.add(ze.getName());
                    }
                }
            }
            in.close();
            return jarClasses;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Find Resources In Jar Error!");
        }
    }

    /**
     * 取得JAR文件中的文件中class文件信息
     * @param jarFile
     * @param packageName
     * @return
     */
    public static List<Class<?>> loadClassesInJar(File jarFile,String packageName) {
        List<Class<?>> klassList = new ArrayList<Class<?>>();
        ClassLoader classLoader = getClassLoader();

        try {
            List<String> paths = findResourcesInJar(jarFile, packageName);
            for (String klassPath : paths) {
                if (klassPath.endsWith(".class")) {
                    String classCanonicalName = klassPath.substring(0,klassPath.lastIndexOf("."));
                    classCanonicalName = classCanonicalName.replace('/', '.');
                    Class<?> klass = classLoader.loadClass(classCanonicalName);
                    klassList.add(klass);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Load Classes In Jar Error!");
        }
        return klassList;
    }
}
